const net = require("net");
const Singleton = require("../Singleton");
const {parseBitPacket, printPacketBit} = require("../utils")
const ImageRequestPacket = require("./ImageRequestPacket");
const ImageResponsePacket = require("./ImageResponsePacket");
const LocalList = require("../LocalList");
const {setOrigin, setLocalImageSocketAddress} = require("../State");
const {queryPeer} = require("../QueryPeer");
function getRequestType(request_type) {
    let response_types = ['Query', 'Found', 'Not found', 'Busy'];
    return response_types[request_type];
}
const ImageTypesNames = {
    1: 'BMP',
    2: 'JPEG',
    3: 'GIF',
    4: 'PNG',
    5: 'TIFF',
    15: 'RAW'
}
let timestamp;
class ImageServer {
    constructor() {
        this.clientSocket = null;
    }
    createServer(address, port) {
        return new Promise((resolve) => {
            this.server = net.createServer((socket) => {
                let chunks = [];
                socket.on('data', (chunk) => {
                    chunks.push(...chunk);
                    const packet_type = parseBitPacket(chunks, 4, 8);
                    if (packet_type === 0) {
                        // this is client request image
                        this.clientSocket = socket;
                        this.handleClientQuery(socket, chunks);
                    }
                    if (packet_type === 1) {
                        // this is peer found image and sent it
                        this.handlePeerSend(socket, chunks);
                    }
                });
            });
            this.server.listen(port, address, () => {
                let address = this.server.address().address;
                let port = this.server.address().port;
                this.address = address;
                this.port = port;
                setLocalImageSocketAddress(address, port);
                console.log(`ImageDB server is started at timestamp: ${Singleton.getTimestamp()} and is listening on ${address}:${port}`);
                resolve();
            });
        })

    }

    handleClientQuery(socket, chunks) {
        let data = ImageRequestPacket.parse(chunks);
        timestamp = Singleton.getTimestamp();
        console.log(`\nClient-${timestamp} is connected at timestamp: ${timestamp}`);
        printPacketBit(chunks);
        console.log(`\nClient-${timestamp} requests: 
              --ITP version: ${data.v}
              --Timestamp: ${data.timestamp}
              --Request type: ${getRequestType(data.request_type)}
              --Image file extension(s): ${ImageTypesNames[data.image_type].toLowerCase()}
              --Image file name: ${data.image_file_name}`);
        // 1. check if local has this image
        let image_data = LocalList.findImageFile(data.image_type, data.image_file_name);
        if (image_data) {
            // local has this image
            let p = ImageResponsePacket.build(
                7,
                1,
                Singleton.getSequenceNumber(),
                Singleton.getTimestamp(),
                image_data
            );
            socket.write(p);
            socket.end();
        } else {
            // local doesn't have this image
            setOrigin(this.address, this.port);
            queryPeer(data.image_type, data.image_file_name)
                .then(() => {

                });
        }
    }

    handlePeerSend(socket, chunks) {
        // get image from peer, send to client
        console.log(`ITP packet response received to forward the image to the client`);
        let data = ImageResponsePacket.parse(chunks);
        let p = ImageResponsePacket.build(7,
            1,
            Singleton.getSequenceNumber(),
            Singleton.getTimestamp(),
            data.image_data
        );
        this.clientSocket.write(p);
        this.clientSocket.end();
        console.log(`Client-${timestamp} closed the connection`);
        socket.end();
    }
}

module.exports = ImageServer;